package com.crimsec.utils.snmp.model;

import java.io.Serializable;
import java.util.ArrayList;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 * $Id$ представляет дерево переменных MIB
 */
@Entity
@Table(name = "mibent")
@XmlRootElement
@XmlType(name = "mibent", propOrder = {"name", "enttype", "mibdb", "parent"})//TODO:maybe proporder here ?
@NamedQueries({
    @NamedQuery(name = "Mibent.findAll", query = "SELECT m FROM Mibent m"),
    @NamedQuery(name = "Mibent.findById", query = "SELECT m FROM Mibent m WHERE m.id = :id"),
    @NamedQuery(name = "Mibent.findByName", query = "SELECT m FROM Mibent m WHERE m.name = :name")})
public class Mibent extends AbstractEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    //
    @Id
    @Basic(optional = false)
    @Column(name = "id")
    private Short id;
    //числовой идентификатор согласно RFC
    @Basic(optional = false)
    @Column(name = "inmib_id")
    private Short inmibId;
    //имя переменной MIB (i.e sysUpTime or system)
    @Basic(optional = false)
    @Column(name = "name")
    private String name;
    //ссылка на старший номер иерархии MIB
    @ManyToOne(fetch = FetchType.EAGER)//старшие объекты иерархии всегда нужны для построения длинного имени
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    private Mibent parent;
    //ссылка на базу в которой определена переменная mib
    @ManyToOne(fetch = FetchType.EAGER)//должно быть недорогой операцией, поскольку таблица mibdb, по сути, маленький справочник
    @JoinColumn(name = "mibdb_id", referencedColumnName = "id")
    private Mibdb mibdb;
    // ссылка на тип snmp (строка, время, хост-строка, OID ... )   
    @Column(name = "type_id")
    private Short type;

    public Mibent() {
    }

    public Mibent(Short id, Short inmibId, String name, Mibent parent, Mibdb mibdb, Enttype enttype) {
        this.id = id;
        this.inmibId = inmibId;
        this.name = name;
        this.parent = parent;
        this.mibdb = mibdb;
        this.setEnttype(enttype);
    }

    /**
     *
     * @return an ArrayList contains parent->child chain for this snmp entity
     */
    public ArrayList<Mibent> getObjectIdentifier() {
        ArrayList<Mibent> result = (getParent() != null) ? parent.getObjectIdentifier() : new ArrayList<Mibent>(7);
        result.add(this);
        return result;
    }

    public String getObjectIdentifierString() {
        return getOID(false);
    }

    public String getObjectIdentifierDigit() {
        return getOID(true);
    }

    private String getOID(boolean digit) {
        StringBuilder br = new StringBuilder(255);
        ArrayList<Mibent> oi = getObjectIdentifier();
        for (Mibent ment : oi) {
            if (digit) {
                br.append(ment.getInmibId());
            } else {
                br.append(ment.getName());
            }
            br.append(".");
        }
        br.deleteCharAt(br.lastIndexOf("."));
        return br.toString();
    }

    public static String getNameFromOID(String oid) {
        int dotI = oid.lastIndexOf(".");
        if (dotI > -1) {
            return oid.substring(oid.lastIndexOf(".") + 1);
        } else {
            return oid;
        }

    }

    @XmlAttribute
    public Short getId() {
        return id;
    }

    public void setId(Short id) {
        this.id = id;
    }

    public Mibent getParent() {
        return parent;
    }

    public void setParent(Mibent parent) {
        this.parent = parent;
    }

    @XmlAttribute
    public Short getInmibId() {
        return inmibId;
    }

    public void setInmibId(Short inmibId) {
        this.inmibId = inmibId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Mibdb getMibdb() {
        return mibdb;
    }

    public void setMibdb(Mibdb mibdb) {
        this.mibdb = mibdb;
    }

    public Enttype getEnttype() {
        return Enttype.parse(this.type);
    }

    public final void setEnttype(Enttype enttype) {
        this.type = (short) enttype.getValue();
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Mibent)) {
            return false;
        }
        Mibent other = (Mibent) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.crimsec.utils.snmp.model.Mibent[ id=" + id + ",name=" + name + " ]";
    }
}
